//! \file thread.hpp
//! \brief Purewell Library Thread Header
//! \author Yubin Lim (purewell@gmail.com)
//! \since 2008-01-25

#ifndef __PWHDR_THREAD_HPP__
#define __PWHDR_THREAD_HPP__

#include "threadobject.hpp"

namespace purewell
{

class PWThreadAttribute;

//! \brief Thread.
class PWThread : public PWThreadObject
{
public:
	//! \brief Initialize thread.
	//! \param[in] param Parameter for PWThread::onStart method.
	//! \param[in] pattr Attrubition for thread.
	//! \return On success, true.
	virtual bool initialize(void* param,
		const PWThreadAttribute* pattr=NULL);

	//! \brief Destroy thread. This function do not stop thread.
	virtual void destroy(void);

public:
	//! \brief Wait until thread is over.
	//! \param[out] ret Result of thread.
	//! \return On success, true.
	bool wait(void** ret);

	//! \brief Make detached thread.
	void detach(void);

	//! \brief Get result of thread.
	//! \return The result of thread.
	void* getResult(void);

	//! \brief Get result of thread.
	//! \return The result of thread.
	const void* getResult(void) const;

	//! \brief Get parameter of thread.
	//! \return The parameter of thread.
	void* getParameter(void);

	//! \brief Get parameter of thread.
	//! \return The parameter of thread.
	const void* getParameter(void) const;

protected:
	//! \brief To do. Callback.
	//! \param[in,out] value User parameter.
	//! \return The result of thread. (user defined)
	virtual void* onStart(void* value);

	//! \brief Exit thread.
	//! \param[in] value The result of thread.
	//! \warning DO NOT CALL THIS METHOD OUT OF 'onStart'!
	void exit(void* value);

public:
	explicit PWThread();
	virtual ~PWThread();

private:
	explicit PWThread(const PWThread&);
	PWThread& operator = (const PWThread&) {return *this;}
	static void* _threadProc(void*);
};

//! \brief Thread atttribute
class PWThreadAttribute : public PWThreadObject
{
public:
	//! \brief Create attribute object.
	//! \return On success, attribute instance pointer.
	//!	In error case, NULL.
	static PWThreadAttribute* create(void);

	//! \brief Create attribute object array.
	//! \param[in] count Array size.
	//! \return On success, the first attribute instance pointer.
	//!	In error case, NULL.
	static PWThreadAttribute* createArray(size_t count);

	//! \brief Release attribute object.
	//! \param[in,out] op Attribute object pointer.
	static void release(PWThreadAttribute* op);

	//! \brief Release attribute object array.
	//! \param[in,out] op The 1st attribute object pointer of array.
	static void releaseArray(PWThreadAttribute* op);

public:
	//! \brief Set thread scope.
	//! \param[in] type Scope type.
	//! \return On success, true.
	bool setScope(int type);

	//! \brief Get thread scope.
	//! \param[out] type Scope type.
	//! \return On success, true.
	bool getScope(int& type) const;

	//! \brief Set detach mode.
	//! \param[in] detached Use detached thread.
	//! \return On success, true.
	bool setDetach(bool detached);

	//! \brief Get detach mode.
	//! \param[out] detached Detach mode.
	//! \return On success, true.
	bool getDetach(bool& detached) const;

	//! \brief Set stack guard size.
	//! \param[in] size Guard size.
	//! \return On success, true.
	bool setGuardSize(size_t size);

	//! \brief Get stack guard size.
	//! \param[out] size Guard size.
	//! \return On success, true.
	bool getGuardSize(size_t& size) const;

	//! \brief Set stack.
	//! \param[in] stack Stack address.
	//! \param[in] size Stack size.
	//! \return On success, true.
	bool setStack(void* stack, size_t size);

	//! \brief Get stack.
	//! \param[out] stack Stack address.
	//! \param[out] size Stack size.
	//! \return On success, true.
	bool getStack(void*& stack, size_t& size) const;

	//! \brief Set stack size.
	//! \param[in] size Stack size.
	//! \return On success, true.
	bool setStackSize(size_t size);

	//! \brief Get stack size.
	//! \param[out] size Stack size.
	//! \return On success, true.
	bool getStackSize(size_t& size) const;

private:
	explicit PWThreadAttribute();
	virtual ~PWThreadAttribute();

private:
	PWThreadAttribute(const PWThreadAttribute&) {}
	PWThreadAttribute& operator = (const PWThreadAttribute&) {return *this;}

};

};


#endif//!__PWHDR_THREAD_HPP__

